﻿using System;
using System.Collections.Generic;
using System.Text;

namespace System.Reflection
{
    internal delegate object DynamicFieldGetHandler(object obj);

    internal delegate void DynamicFieldSetHandler(object obj, object value);

	public class DynamicFieldInfo : IDynamicFieldInfo
    {
        Type type;

        FieldInfo info;

        DynamicFieldSetHandler setHandler = null;

        DynamicFieldGetHandler getHandler = null;

        public DynamicFieldInfo(Type type, FieldInfo info)
        {
            this.type = type;
            this.info = info;
        }

        public object GetValue(object obj)
        {
            int key = info.MetadataToken;

            if (this.getHandler != null)
            {
                return this.getHandler(obj);
            }

            if (DynamicCacheFactory<DynamicFieldGetHandler>.Instance.Contains(key))
            {
                this.getHandler = DynamicCacheFactory<DynamicFieldGetHandler>.Instance.GetValue(key);
            }
            else
            {
                this.getHandler = DynamicMethodFactory.CreateGetHandler(type, info);
                DynamicCacheFactory<DynamicFieldGetHandler>.Instance.AddValue(key, this.getHandler);
            }

            return this.getHandler(obj);
        }

        public void SetValue(object obj, object value)
        {
            int key = info.MetadataToken;

            if (this.setHandler != null)
            {
                this.setHandler(obj, value);

                return;
            }

            if (DynamicCacheFactory<DynamicFieldSetHandler>.Instance.Contains(key))
            {
                this.setHandler = DynamicCacheFactory<DynamicFieldSetHandler>.Instance.GetValue(key);
            }
            else
            {
                this.setHandler = DynamicMethodFactory.CreateSetHandler(type, info);

                DynamicCacheFactory<DynamicFieldSetHandler>.Instance.AddValue(key, this.setHandler);
            }

            this.setHandler(obj, value);
        }
    }
}
